from datetime import datetime
from wsgiref.handlers import format_date_time
from time import mktime
import hashlib
import base64
import hmac
from urllib.parse import urlencode
import json
import requests
import os
from dotenv import load_dotenv


env_path = os.path.join(os.path.dirname(__file__), '..', 'ak.envs')
load_dotenv(dotenv_path=env_path)

class AssembleHeaderException(Exception):
    def __init__(self, msg):
        self.message = msg

class Url:
    def __init__(self, host, path, schema):
        self.host = host
        self.path = path
        self.schema = schema

def sha256base64(data):
    sha256 = hashlib.sha256()
    sha256.update(data)
    digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
    return digest

def parse_url(requset_url):
    stidx = requset_url.index("://")
    host = requset_url[stidx + 3:]
    schema = requset_url[:stidx + 3]
    edidx = host.index("/")
    if edidx <= 0:
        raise AssembleHeaderException("invalid request url:" + requset_url)
    path = host[edidx:]
    host = host[:edidx]
    u = Url(host, path, schema)
    return u

def assemble_ws_auth_url(requset_url, method="POST", api_key="", api_secret=""):
    u = parse_url(requset_url)
    host = u.host
    path = u.path
    now = datetime.now()
    date = format_date_time(mktime(now.timetuple()))
    signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(host, date, method, path)
    signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                             digestmod=hashlib.sha256).digest()
    signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
    authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
        api_key, "hmac-sha256", "host date request-line", signature_sha)
    authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
    values = {
        "host": host,
        "date": date,
        "authorization": authorization
    }
    return requset_url + "?" + urlencode(values)

def translate_text(text, direction='chinese_to_french'):

    APPId = os.getenv('XFYUN_TRANS_APPID') or os.getenv('XFYUN_APPID')
    APISecret = os.getenv('XFYUN_TRANS_API_SECRET') or os.getenv('XFYUN_API_SECRET')
    APIKey = os.getenv('XFYUN_TRANS_API_KEY') or os.getenv('XFYUN_API_KEY')


    if direction == 'chinese_to_french':
        from_lang = "cn"
        to_lang = "fr"
    elif direction == 'french_to_chinese':
        from_lang = "fr"
        to_lang = "cn"
    else:
        return False, None, 0, "无效的翻译方向"


    url = 'https://itrans.xf-yun.com/v1/its'

    body = {
        "header": {
            "app_id": APPId,
            "status": 3,
            "res_id": "its_en_cn_word"
        },
        "parameter": {
            "its": {
                "from": from_lang,
                "to": to_lang,
                "result": {}
            }
        },
        "payload": {
            "input_data": {
                "encoding": "utf8",
                "status": 3,
                "text": base64.b64encode(text.encode("utf-8")).decode('utf-8')
            }
        }
    }

    try:
        request_url = assemble_ws_auth_url(url, "POST", APIKey, APISecret)
        headers = {'content-type': "application/json", 'host': 'itrans.xf-yun.com', 'app_id': APPId}


        response = requests.post(request_url, data=json.dumps(body), headers=headers)


        tempResult = json.loads(response.content.decode())

        if tempResult["header"]["code"] == 0:

            decode_text = base64.b64decode(tempResult['payload']['result']['text']).decode()
            trans_result = json.loads(decode_text)
            final_translation = trans_result["trans_result"]["dst"]

            char_count = len(text)
            return True, final_translation, char_count, None
        else:
            error_msg = f"code={tempResult['header']['code']}, msg={tempResult['header']['message']}"
            return False, None, len(text), error_msg

    except Exception as e:
        return False, None, len(text), str(e)
